home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / The Hacks / TECalc ƒ / GeniusBar.c next >
Encoding:
C/C++ Source or Header  |  2001-06-23  |  5.7 KB  |  290 lines

  1. /*
  2.     
  3.     GeniusBar
  4.     
  5.     Joshua Juran
  6.     
  7. */
  8.  
  9. #include <string.h>
  10.  
  11. #include <Controls.h>
  12. #include <ControlDefinitions.h>
  13. #include <Events.h>
  14. #include <MacWindows.h>
  15. #include <Processes.h>
  16. #include <QuickDraw.h>
  17. #include <Resources.h>
  18.  
  19. // Needed for globals
  20. #include <A4Stuff.h>
  21.  
  22. #define _GetNextEvent 0xA970
  23.  
  24. static pascal short PatchedGetNextEvent(EventMask, EventRecord *theEvent);
  25.  
  26. typedef pascal short (*GetNextEventProcPtr)(EventMask, EventRecord *);
  27. static GetNextEventProcPtr    origGetNextEvent;
  28.  
  29. const char *gLastString;
  30.  
  31. static short UpdateString(const char *inString)
  32. {
  33.     long oldA4;
  34.     short result;
  35.     
  36.     oldA4 = SetCurrentA4();
  37.     
  38.     result = strcmp(gLastString, inString) != 0;
  39.     
  40.     gLastString = inString;
  41.     
  42.     SetA4(oldA4);
  43.     
  44.     return result;
  45. }
  46.  
  47. static short IsFinderInForeground()
  48. {
  49.     OSErr err;
  50.     ProcessSerialNumber psn;
  51.     ProcessInfoRec procInfo;
  52.     
  53.     procInfo.processInfoLength = sizeof procInfo;
  54.     procInfo.processName = NULL;
  55.     procInfo.processAppSpec = NULL;
  56.     
  57.     err = GetFrontProcess(&psn);
  58.     if (err) return 0;
  59.     
  60.     err = GetProcessInformation(&psn, &procInfo);
  61.     if (err) return 0;
  62.     
  63.     return (procInfo.processSignature == 'MACS');
  64. }
  65.  
  66. static short IsPointingToTrash(Point inPt)
  67. {
  68.     GrafPtr wMgrPort;
  69.     Rect rect;
  70.     
  71.     GetWMgrPort(&wMgrPort);
  72.     rect = wMgrPort->portRect;
  73.     
  74.     rect.bottom -= 32;
  75.     rect.right -= 32;
  76.     rect.top = rect.bottom - 32;
  77.     rect.left = rect.right - 32;
  78.     
  79.     return PtInRect(inPt, &rect);
  80. }
  81.  
  82. static const char *GetGeniusString(EventRecord *theEvent)
  83. {
  84.     short locationCode;
  85.     WindowPtr wptr;
  86.     const char *geniusMsg = "";
  87.     
  88.     locationCode = FindWindow(theEvent->where, &wptr);
  89.     
  90.     switch (locationCode) {
  91.     case inDesk:
  92.         if (!IsFinderInForeground()) {
  93.             geniusMsg = "Click here to switch to the Finder.";
  94.         } else {
  95.             if (IsPointingToTrash(theEvent->where)) {
  96.                 geniusMsg = "This is GeniusBar, a hack by Joshua Juran.";
  97.             } else return NULL;
  98.         }
  99.         break;
  100.     case inMenuBar:
  101.         geniusMsg = "Click here to choose from a menu.";
  102.         break;
  103.     case inDrag:
  104.         geniusMsg = "Click here to move this window.";
  105.         break;
  106.     case inGrow:
  107.         geniusMsg = "Click here to resize this window.";
  108.         break;
  109.     case inGoAway:
  110.         geniusMsg = "Click here to close this window.";
  111.         break;
  112.     case inZoomIn:
  113.         geniusMsg = "Click here to un-zoom this window.";
  114.         break;
  115.     case inZoomOut:
  116.         geniusMsg = "Click here to zoom this window.";
  117.         break;
  118.     case inCollapseBox:
  119.         geniusMsg = "Click here to collapse this window.";
  120.         break;
  121.     case inSysWindow:
  122.         geniusMsg = "This is a system window.";
  123.     case inContent:
  124.         {
  125.             ControlHandle control;
  126.             Point pt = theEvent->where;
  127.             short part;
  128.             Rect rect;
  129.             short vertical;
  130.             GrafPtr savePort;
  131.             
  132.             GetPort(&savePort);
  133.             SetPort(wptr);
  134.             GlobalToLocal(&pt);
  135.             part = FindControl(pt, wptr, &control);
  136.             SetPort(savePort);
  137.             rect = (**control).contrlRect;
  138.             vertical = rect.bottom - rect.top > rect.right - rect.left;
  139.             
  140.             switch (part) {
  141.             case kControlButtonPart:
  142.                 geniusMsg = "Click here to push this button.";
  143.                 break;
  144.             case kControlCheckBoxPart:
  145.                 geniusMsg = "Click here to enable this option.";
  146.                 break;
  147.             case kControlUpButtonPart:
  148.                 geniusMsg = vertical 
  149.                     ? "Click here to scroll up."
  150.                     : "Click here to scroll left.";
  151.                 break;
  152.             case kControlDownButtonPart:
  153.                 geniusMsg = vertical
  154.                     ? "Click here to scroll down."
  155.                     : "Click here to scroll right.";
  156.                 break;
  157.             case kControlPageUpPart:
  158.                 geniusMsg = vertical
  159.                     ? "Click here to scroll up by a page."
  160.                     : "Click here to scroll left by a page.";
  161.                 break;
  162.             case kControlPageDownPart:
  163.                 geniusMsg = vertical
  164.                     ? "Click here to scroll down by a page."
  165.                     : "Click here to scroll right by a page.";
  166.                 break;
  167.             case kControlIndicatorPart:
  168.                 geniusMsg = "Click here to scroll to an arbitrary position.";
  169.                 break;
  170.             default:
  171.                 return NULL;
  172.                 break;
  173.             }
  174.         }
  175.         break;
  176.     default:
  177.         return NULL;
  178.         break;
  179.     }
  180.     return geniusMsg;
  181. }
  182.  
  183. static DrawGeniusMessage(const char *inString)
  184. {
  185.     GrafPtr savePort;
  186.     CGrafPtr cWMgrPort;
  187.     short mbarHeight;
  188.     Rect rect;
  189.     RGBColor saveColor, menuColor;
  190.     long len = strlen(inString);
  191.     
  192.     GetPort(&savePort);
  193.     GetCWMgrPort(&cWMgrPort);
  194.     mbarHeight = GetMBarHeight();
  195.     
  196.     rect.top = 1;
  197.     rect.bottom = mbarHeight - 2;
  198.     rect.left = 8;
  199.     rect.right = cWMgrPort->portRect.right - 8;
  200.     
  201.     SetPort((GrafPtr)cWMgrPort);
  202.     GetBackColor(&saveColor);
  203.     
  204.     GetCPixel(5, 5, &menuColor);
  205.     RGBBackColor(&menuColor);
  206.     
  207.     EraseRect(&rect);
  208.     
  209.     MoveTo(8, mbarHeight - 6);
  210.     DrawText(inString, 0, len);
  211.     
  212.     RGBBackColor(&saveColor);
  213.     SetPort(savePort);
  214. }
  215.  
  216. static void Payload(EventRecord *theEvent)
  217. {
  218.     if ((theEvent->modifiers & btnState) == 0) {
  219.         InvalMenuBar();
  220.     } else {
  221.         const char *str = GetGeniusString(theEvent);
  222.         if (UpdateString(str)) {
  223.             if (str == NULL) {
  224.                 InvalMenuBar();
  225.             } else {
  226.                 DrawGeniusMessage(str);
  227.             }
  228.         }
  229.     }
  230. }
  231.  
  232. static pascal short PatchedGetNextEvent(EventMask eventMask, EventRecord *theEvent)
  233. {
  234.     long oldA4;
  235.     short result;
  236.     
  237.     oldA4 = SetCurrentA4();
  238.     
  239.     result = origGetNextEvent(eventMask, theEvent);
  240.     
  241.     Payload(theEvent);
  242.     
  243.     SetA4(oldA4);
  244.     
  245.     return result;
  246. }
  247.  
  248. static ProcPtr ApplyTrapPatch(short trap, ProcPtr patchPtr)
  249. {
  250.     ProcPtr trapPtr;
  251.     
  252.     if (patchPtr == nil)
  253.         return nil;
  254.  
  255.     trapPtr = NGetTrapAddress (trap, (trap & 0x0800) ? ToolTrap : OSTrap);
  256.     NSetTrapAddress (patchPtr, trap, (trap & 0x0800) ? ToolTrap : OSTrap);
  257.     return trapPtr;
  258. }
  259.  
  260. void main(void)
  261. {
  262.     long oldA4;
  263.     UniversalProcPtr procPtr;
  264.     Handle    initCode = nil;
  265.     THz        oldZone;
  266.     
  267.     oldA4 = SetCurrentA4();
  268.     
  269.     oldZone = GetZone();
  270.     SetZone(SystemZone());
  271.     
  272.     initCode = (Handle)Get1Resource('INIT', 0);
  273.     if (initCode == nil)
  274.         goto failure;
  275.     
  276.     DetachResource(initCode);
  277.     if (ResError() != noErr) 
  278.         goto failure;
  279.     
  280.     HLockHi(initCode);
  281.     HNoPurge(initCode);
  282.     
  283.     procPtr = ApplyTrapPatch( _GetNextEvent, (ProcPtr)(PatchedGetNextEvent) );
  284.     origGetNextEvent = (GetNextEventProcPtr)procPtr;
  285.     
  286. failure:
  287.     SetZone(oldZone);
  288.     SetA4(oldA4);
  289. }
  290.